package com.powernode.ssm.config;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.CommandLineRunner;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Component;

import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * 该工具类在 Spring Boot 启动时自动执行，用于：
 * 1. 自动探测 spring.datasource.dynamic.datasource 下所有实际配置的数据源名称（不用手动写死）
 * 2. 读取每个数据源的原始配置（如 url、username、password、driver-class-name、type 等）
 * 3. 将配置保存到 Map<String, Map<String, String>> 中，结构清晰，可供后续使用
 * 4. 使用 SLF4J 打印日志，支持通过日志级别（如 DEBUG）控制是否打印详细配置信息
 *
 * 适用于：开发调试、配置校验、数据源导出、文档生成等场景
 */
@Component
public class DynamicDataSourceConfigLogger implements CommandLineRunner {

    private static final Logger log = LoggerFactory.getLogger(DynamicDataSourceConfigLogger.class);

    private final Environment environment;

    // 保存所有数据源的原始配置，结构：Map<数据源名称, Map<配置项名, 配置值>>
    private Map<String, Map<String, String>> dataSourceConfigsMap = new HashMap<>();

    public DynamicDataSourceConfigLogger(Environment environment) {
        this.environment = environment;
    }

    @Override
    public void run(String... args) throws Exception {
        log.info("[🚀] 开始自动探测并加载 spring.datasource.dynamic.datasource 下的原始数据源配置...");

        // 1. ✅ 自动探测所有实际配置了的数据源名称
        Set<String> dataSourceNames = detectDataSourceNames();

        if (dataSourceNames.isEmpty()) {
            log.warn("[⚠️] 未探测到任何数据源配置，请检查 spring.datasource.dynamic.datasource 下是否配置了数据源");
            return;
        }

        log.debug("[🔍] 探测到的数据源名称有: {}", dataSourceNames);

        // 2. 逐个加载数据源配置
        for (String dsName : dataSourceNames) {
            Map<String, String> config = loadDataSourceConfig(dsName);
            dataSourceConfigsMap.put(dsName, config);

            logDataSourceConfig(dsName, config);
        }

        log.info("[✅] 所有数据源原始配置已加载完成，共 {} 个数据源。配置已保存到内存，可通过 getDataSourceConfigsMap() 获取。", dataSourceConfigsMap.size());
    }

    /**
     * ✅ 自动探测 spring.datasource.dynamic.datasource 下所有实际配置了的数据源名称
     * 只探测那些至少配置了 url 的数据源（避免误探测）
     */
    private Set<String> detectDataSourceNames() {
        // 可能的数据源 key 都是以 spring.datasource.dynamic.datasource.<name>.url 开头的
        // 我们只要找出所有存在 .url 配置的 <name>

        return Stream.of(
                        "jdbc", "oracle", "postgresql", "mybatis", "mysql", "hana", "sqlserver", "db2" // 常见数据源名，也可完全不写，下面通过 key 探测
                )
                .filter(dsName -> isDataSourceConfigured(dsName))
                .collect(Collectors.toSet());
    }

    /**
     * 检测某个数据源名称是否配置了 url（或其它关键字段，这里只判断 url）
     */
    private boolean isDataSourceConfigured(String dataSourceName) {
        return environment.getProperty("spring.datasource.dynamic.datasource." + dataSourceName + ".url") != null;
    }

    /**
     * 读取单个数据源的配置项，如 url、username、password、driver-class-name、type
     */
    private Map<String, String> loadDataSourceConfig(String dataSourceName) {
        String prefix = "spring.datasource.dynamic.datasource." + dataSourceName + ".";

        Map<String, String> config = new HashMap<>();
        config.put("url", environment.getProperty(prefix + "url"));
        config.put("username", environment.getProperty(prefix + "username"));
        config.put("password", environment.getProperty(prefix + "password"));
        config.put("driver-class-name", environment.getProperty(prefix + "driver-class-name"));
        config.put("type", environment.getProperty(prefix + "type"));

        // 如有其它配置，如 druid.xxx，也可继续添加
        // config.put("druid.initial-size", environment.getProperty(prefix + "druid.initial-size"));

        return config;
    }

    /**
     * 使用 SLF4J 打印单个数据源的配置（支持日志级别控制）
     */
    private void logDataSourceConfig(String dataSourceName, Map<String, String> config) {
        log.debug("[🔌 数据源: {}]", dataSourceName);
        log.debug("   🌐 URL: {}", config.get("url"));
        log.debug("   👤 用户名: {}", config.get("username"));
        log.debug("   🔐 密码: {}", config.get("password") != null ? "***" : "未设置");
        log.debug("   🚗 驱动类名: {}", config.get("driver-class-name"));
        log.debug("   🏗️  类型: {}", config.get("type"));
    }

    /**
     * ✅ 对外提供方法：获取所有数据源的原始配置 Map
     * 结构：Map<String, Map<String, String>>
     * key: 数据源名称，如 "jdbc"
     * value: 该数据源的配置，如 url、username、password、driver-class-name、type
     */
    public Map<String, Map<String, String>> getDataSourceConfigsMap() {
        return dataSourceConfigsMap;
    }

    /**
     * 获取数据源驱动类名
     * @param dataSourceName 数据源名称
     * @return 驱动类名
     */
    public String getDriverClassName(String dataSourceName) {
        Map<String, String> stringStringMap = dataSourceConfigsMap.get(dataSourceName);
        return stringStringMap != null ? stringStringMap.get("driver-class-name") : null;
    }

    /**
     * 获取数据源url
     * @param dataSourceName 数据源名称
     * @return 驱动类名
     */
    public String getURL(String dataSourceName) {
        Map<String, String> stringStringMap = dataSourceConfigsMap.get(dataSourceName);
        return stringStringMap != null ? stringStringMap.get("url") : null;
    }

}